/**
 * util - Various general-purpose utility functions to enhance JavaScript.
 * 
 */ 
if (!util) { var util = (function() {
var my = {};

/**
 * Regular expression for detecting an absolute path.
 */
my.ABS_RE = /^(?:(?:\w+:)|\/)/;

/**
 * Regular expression for getting the directory of a path.
 */
my.DIRECTORY_RE = /^(.*\/).*$/;

/**
 * Return the current script element.
 */
my.getCurrentScript = function getCurrentScript() {
  var scripts = document.getElementsByTagName("script");
  return scripts[scripts.length-1];
}
 
/**
 * Get the containing directory URL of the current script.
 * 
 * util.getCurrentDir() -> String
 *   Returns src of current script or emptry string when there is no src.
 *
 * util.getCurrentDir(true)
 *   -> {dir : <String/null>, element : <HTMLScriptElement>}
 *   Returns a plain Object that contains the script dir (or empty string when
 *   there is no src) and the script element.
 * 
 * The final forward slash is included, unless there is no src.
 */
my.getCurrentDir = function getCurrentDir(returnScript) {
  var curScript = my.getCurrentScript();
  var curScriptSrc = curScript.src;  
  curDir = (curScriptSrc && curScriptSrc.indexOf("/") != -1) ?
           my.DIRECTORY_RE.exec(curScriptSrc)[1] : ""
  return returnScript ? {dir : curDir, element : curScript} : curDir;
}

/**
 * Converts a URL to an absolute URL based on the given directory.
 * WARNING: May not work in some specific cases. (IE6 is known to have issues.)
 * 
 */
my.toAbs = function toAbs (url, dir) {
  if (dir===undefined) dir = my.getCurrentDir();
  a = document.createElement("a");
  a.href = dir + url;
  return a.href;
}

var _includeChainIsRunning = false;
var _srcsToInclude = [];
var _srcInclusionDirs = [];
var _srcsIncluded = [];
var _lastSrcIncluded = "";

/**
 * Include the given source files by creating new script elements.
 * 
 * Each script element will be inserted into the document immediately following
 * the script element from which the util.include() function was called.
 * 
 * Scripts may be loaded asynchronously, but they will be loaded in the order
 * specified.
 * 
 * Should one script, called script "A", queue an inclusion for another script,
 * "B", the scripts that were queued by "A" will not be included until after the
 * scripts in "B" are included.
 * 
 * No script will ever be included twice. If a duplicate or equivalent URL is
 * used more than once, only the first occurence will have any effect.
 * Subsequence occurences will be ignored.
 */
my.include = function include() {
  // Get a list of all loaded scripts.
  var scripts = document.getElementsByTagName("script");
  _srcsIncluded = [];
  for (var i=0; i<scripts.length; i++) {
    var script = scripts[i];
    if (script.src)
      _srcsIncluded.push(my.toAbs(script.src));
  }
  var dir = my.getCurrentDir();
  for (i=0; i<arguments.length; i++) {
    _srcsToInclude.splice(i, 0, arguments[i]);
    _srcInclusionDirs.splice(i, 0, dir);
  }
  if (!_includeChainIsRunning) {
    _includeChainIsRunning = true;
    _includeNext();
  }
};

function _includeNext() {
  if (_lastSrcIncluded != "")
    console.log("LOADED: " + _lastSrcIncluded);
  
  // If there are scripts to load
  if (_srcsToInclude.length > 0) {
    
    // Get the data for this inclusion
    var src = _srcsToInclude.shift(),
        dir = _srcInclusionDirs.shift(),
        absSrc = my.toAbs(src, dir);
    
    // Don't include scripts that have already been included
    if (_srcsIncluded.indexOf(absSrc) == -1) {
      _srcsIncluded.push(absSrc);
      
      console.log ("LOADING: " + absSrc)
      
      // If the src is not absolute, prepend the current directory.
      if (!my.ABS_RE.test(src))
        src = dir + src;
        
      // Create and append the current script element.
      var newScript = document.createElement("script");
      newScript.onload =_includeNext;
      newScript.type = "text/javascript";
      newScript.src = src;
      my.insertAfter(newScript, my.getCurrentScript());
      
      _lastSrcIncluded = absSrc;
    }
    else
      console.log("ALREADY LOADED: " + absSrc);
  }
  else {
    _includeChainIsRunning = false;
    _lastSrcIncluded = "";
  }
}

/**
 * Insert a node after the given reference node in the reference node's parent.
 */
my.insertAfter = function insertAfter(node, referenceNode) {
    referenceNode.parentNode.insertBefore(node, referenceNode.nextSibling);
}

/**
 * Determine whether or not a given object was made using an object literal
 * Credit: StackOverflow.com, Elijah Grey
 * http://stackoverflow.com/questions/1173549/how-to-determine-if-an-object-is-an-object-literal-in-javascript
 */
my.isObjectLiteral = function isObjectLiteral(obj) {
  if (typeof obj !== "object" || obj === null)
    return false;

  var hasOwnProp = Object.prototype.hasOwnProperty,
  ObjProto = obj;

  // get obj's Object constructor's prototype
  while (Object.getPrototypeOf(ObjProto =
         Object.getPrototypeOf(ObjProto)) !== null);

  // workaround if non-native Object.getPrototypeOf
  if (!Object.getPrototypeOf.isNative)
    for (var prop in obj)
      if (!hasOwnProp.call(obj, prop)
	      && !hasOwnProp.call(ObjProto, prop)) // inherited elsewhere
        return false;

    return Object.getPrototypeOf(obj) === ObjProto;
};

if (!Object.getPrototypeOf) {
  if (typeof ({}).__proto__ === "object") {
    Object.getPrototypeOf = function (obj) {
      return obj.__proto__;
    };
    Object.getPrototypeOf.isNative = true;
 } else {
    Object.getPrototypeOf = function (obj) {
      var constructor = obj.constructor,
        oldConstructor;
        if (Object.prototype.hasOwnProperty.call(obj, "constructor")) {
          oldConstructor = constructor;
          if (!(delete obj.constructor)) // reset constructor
            return null; // can't delete obj.constructor, return null
          constructor = obj.constructor; // get real constructor
          obj.constructor = oldConstructor; // restore constructor
        }
        return constructor ? constructor.prototype : null; // needed for IE
      };
      Object.getPrototypeOf.isNative = false;
  }
} else Object.getPrototypeOf.isNative = true;

// Helper function/class used by clone() and extend()
function _Clone() { }

/**
* Create a clone of the given object.
* 
*   myClone = util.clone(obj[, attrs[, onlyIfAttrsHasOwn[, onlyIfNotSame]]]);
* 
* This creates a new object that uses the given object as its prototype.
* 
* You can specify which attributes should maintain values that differ from
* the original by passing their names as strings in an array or by passing a
* second object with the desired attribute names and values:
* 
* - If an array is passed, the values will be copied from the original to 
*   owned properties of the clone.
* 
* - If a plain object is passed, the attributes of the given object will be 
*   assigned to the clone.
* 
* - If the `onlyIfAttrsHasOwn` flag is set and a non-array object is passed to 
*   attrs, only owned attributes of the attrs object will be copied and
*   attributes inherited from the prototype of `attrs` will not be copied. 
*   Otherwise, all attributes of `attrs` are copied.
* 
* - If the `onlyIfNotSame` flag is set and a non-array object is passed to
*   attrs, then for every attribute in the original for which there is an   
*   attribute of the same name in attrs, the attribute value is only copied from 
*   attrs to the clone if its value is different from the original's.
*   Otherwise, attributes are copied regardless of whether they are the same or
*   not.
* 
* Credit: Oran Looney
* http://oranlooney.com/classes-and-objects-javascript/
*/
my.clone = function clone(obj, attrs, onlyIfAttrsHasOwn, onlyIfNotSame) {
  _Clone.prototype = obj;
  var clone = new _Clone();
  var key;
  if (attrs) {
    if (attrs instanceof Array) {
      for (var i in attrs) {
        clone[attrs[i]] = obj[attrs[i]];
      }
    }
    else {
      if (onlyIfAttrsHasOwn) {
        if (onlyIfNotSame) {
          for (key in attrs)
            if (attrs.hasOwnProperty(key) && obj[key] !== attrs[key])
              clone[key] = attrs[key];
        }
        else {
          for (key in attrs)
            if (attrs.hasOwnProperty(key))
              clone[key] = attrs[key];
        }
      }
      else {
        if (onlyIfNotSame) {
          for (var key in attrs)
            if (obj[key] !== attrs[key])
              clone[key] = attrs[key];
        }
        else {
          for (var key in attrs)
            clone[key] = attrs[key];
        }
      }
    }
  }
  return clone;
}

/**
 * Return a shallow copy of the given object or objects.
 * 
 *  myCopy = util.copyObject(obj1[, obj2[, ...]]);
 * 
 * The object returned will always be a plain object and will have the 
 * original objects' own attributes, but not their inherited attributes or
 * methods. In the case that two or more of the original objects share an
 * attribute, the rightmost object with the attribute always takes precedence.
 */
my.copyObject = function copyObject(obj) {
  var copy = {};
  if (obj) {
    for (var i = 0; i<arguments.length; i++) {
      obj = arguments[i];
      for (var aName in obj) {
        if (obj.hasOwnProperty(aName))
          copy[aName] = obj[aName];
      }
    }
  }
  return copy;
}

/**
 * Creates a new "class" from the given information.
 * 
 *   MyClass = extend(supers, constructor[, methods]);
 *   MyClass = extend(supers, constructor[, method0[, method1[, ...
 *                                                                [methodN]]]]);
 * 
 * The `supers` argument specifies the class or classes from which the 
 * new class will be derived. All classes must extend an existing class, but 
 * if you want to create an effective base class, pass Object.
 * 
 * Pass a single class to supers to use that class as the prototypical base
 * for the new class. Pass an array of classes to use the first item as the
 * protoypical base, and all subsequent items as "psuedo-mixins," wherein the
 * methods of 
 * 
 * `constructor` specifies the function that will be used as the constructor
 * method. Within the context of this method the `this` argument refers to the
 * newly-created instance. Note that the function passed here will be modified.
 * All classes must have a constructor, and that constructor should call the
 * base constructor.
 * 
 * The `methods` argument specifies the methods for the class. Methods of the
 * superclass may be overridden. Within these methods the `this` variable 
 * refers to the calling instance. The `methods` argument can be an Array, an 
 * Object, a Function, or you can choose not to pass it, in which case the class
 * will have no methods except those inherited from the superclass.
 * 
 * Example uses of the util.extend function are below.
 * 
 * Example A: Class with no methods other than the constructor.
 * 
 *  Foo = util.extend(
 *    // This class is a "base" class, so we pass Object as the superclass.
 *    Object,
 * 
 *    // The name `Foo` is optional here, but its presence makes debugging 
 *    // easier and is consistent with the constructor naming convention of
 *    // other languages.
 *    function Foo (value) {
 *      this.attr = value;
 *    }
 *  );
 * 
 * Example B: Class with one method other than the constructor.
 * 
 *  Foo = util.extend(
 *    Object,
 *
 *    function Foo (value) {
 *      this.attr = value;
 *    },
 * 
 *    function getAttr() {
 *      return this.attr;
 *    },
 *  );
 * 
 * Example C: Class with multiple methods specified via variable arguments.
 * 
 *  Foo = util.extend(
 *    Object,
 * 
 *    function Foo (value) {
 *      this.attr = value;
 *    },
 * 
 *    function getAttr() {
 *      return this.attr;
 *    },
 *    
 *    function setAttr(attr) {
 *      this.attr = attr;
 *    },
 *    
 *    function showAttr() {
 *      alert(this.attr);
 *    }
 *  ); 
 * 
 * Example D: Class with multiple methods specified via an array literal.
 * 
 *  // This definition gives methods via an Array.
 *  Foo = util.extend(
 *    Object,
 * 
 *    function Foo (value) {
 *      this.attr = value;
 *    },
 *  
 *    [
 *      function getAttr() { return this.attr; },
 *      function setAttr(attr) { this.attr = attr; },
 *      function showAttr() { alert(this.attr); }
 *    ]
 *  );
 * 
 * Example E: Class with multiple methods specified via an object literal.
 * 
 *  Foo = util.extend(
 *    Object,
 * 
 *    function Foo (value) {
 *      this.attr = value;
 *    },
 *    
 *    {
 *      getAttr: function () { return this.attr; },
 *      setAttr: function (attr) { this.attr = attr; },
 *      showAttr: function () { alert(this.attr); }
 *    }
 *  );
 * 
 * In any case, you'll get a new class called Foo whose instances will have
 * the methods given. The class can be instantiated using the syntax:
 *
 *  foo = new Foo(value);
 * 
 * Subclassing is simple:
 * 
 *  SubFoo = util.extend (
 *    Foo,
 * 
 *    // Constructor (required, though it does not have to be named)
 *    function SubFoo(value, value2) {
 *      // Call the base constructor using the provided "superclass" property
 *      this.superclass.call(this, value);
 *      this.value2 = value2;
 *    },
 * 
 *    function getValue () {
 *      return this.value2;
 *    },
 *  
 *    function setValue2 (value2) {
 *      this.value2 = value2;
 *    }
 *  );
 * 
 * If you want to call a superclass' method, you can use the syntax:
 * 
 *  this.superclass.prototype.METHOD.call(this[, ARG0[, ... [, ARGN]]]);
 * 
 * where METHOD is the name of the superclass method to be called and
 * ARG0...ARGN are the arguments to be passed to it.
 * 
 * Use of `util.extend()` has been tested in the most recent versions of
 * Internet Explorer, Firefox, and Chrome at the time of this writing. All
 * manners of providing methods to classes appear to work as intended in every
 * browser mentioned.
 */
my.extend = function extend (supers, c, methods) {
  var superclass, mixins, subP, i, method, mname, initSubCs, nc, classinits,
      classmethods, markers;
  
  // Assert the superclass list
  if (supers instanceof Function) {
    superclass = supers;
    supers = [supers];
  }
  else if (supers instanceof Array) {
    superclass = supers[0];
    supers = supers.slice(); // Work on a copy of the input.
  }
  else
    throw new TypeError("supers must be a function or array.");
  
  // Create the subclass' base prototype
  subP = my.clone(superclass.prototype);
  
  // Build the mixin clone prototype chain.
  mixins = supers.slice(1);
  mixins.reverse();
  for (i=0; i<mixins.length; i++) {
    subP = my.clone(subP, mixins[i].prototype, false, true);
  }
  mixins.reverse();
  
  // Assert the constructor
  if (!(c instanceof Function))
    throw new TypeError("c must be a function.");
  
  // Process the methods, if any were given
  if (methods) {
    // If `methods` is a single function (and therefore not an array or other
    // object), it and the remaining arguments should be considered the
    // methods list.
    if (methods instanceof Function) {
      methods = Array.prototype.slice.call(arguments, 2);
    }
    // If `methods` was passed as an array, determine the names of the methods
    // from the functions themselves.
    if (methods instanceof Array) {
      var methodsArray = methods;
      methods = {};
      for (i=0; i<methodsArray.length; i++) {
        method = methodsArray[i];
        mname = my.getFunctionName(method);
        if (!mname) {
          throw new TypeError(
            "Encountered unnamed static property while " +
            "creating new class:\n    " + method.toString()
          );
        }
        methods[mname] = method;
      }
    }
  
    // Process special methods
    classmethods = {};
    classinits = {};
    for (mname in methods) {
      method = methods[mname];
      markers = method.__markers__ || {};
      // Class init methods should be stored for execution at the end of the
      // class processing.
      if (markers.classinit) {
        classinits[mname] = method;
      }
      // Class methods should be bound to the class and added to the
      // class itself.
      else if (markers.classmethod) {
        classmethods[mname] = c[mname] = method;
        method.bind(c);
      }
    }

    // Remove classinits from the methods to add.
    for (mname in classinits)
      delete methods[mname];
  }
  
  // Apply the constructor and method list (if any)
  subP = my.clone(subP, methods)
  subP.constructor = c;
  c.prototype = subP;
  
  // Apply the last couple of special class properties.
  
  c.isInstance = _isInstance;
  
  // Run the classinits, if any.
  if (classinits)
    for (mname in classinits)
      classinits[mname].call(c, supers, methods, classmethods, classinits);
  
  return c;
}

var _isInstance = function isInstance (obj) {
  var i,j, mixins;
  if (obj instanceof this)
    return true;
  mixins = obj.constructor.mixins;
  if (mixins) {
    for (i=0; i<mixins.length; i++) {
      if (this === mixins[i])
        return true;
    }
  }
  return false;
}

my.isInstance = function isInstance(cls, obj) {
  return _isInstance.call(cls, obj);
}

/**
* Marks the given function as a class method and returns it.
*   
*   util.extend (
*     ...
*     util.classmethod(
*     function myMethod() {
*       ...
*     }) 
*     ...
*   );
* 
* This does not modify the behavior of the function; it merely marks it as a
* class method so the class creation system knows to deal with it differently
* than normal methods. As the example above shows, it is intended to be used
* within a class definition.
* 
* Note that classmethods and classinits are MUTUALLY EXLUCSIVE. A method cannot
* be both classmethod and classinit; this will result in an error.
*/
my.classmethod = function classmethod(func) {
  var markers = func.__markers__ = func.__markers__ || {};
  if (markers.classinit)
    throw new TypeError(
      'Function "' + my.getFunctionName(func) +
      '" cannot be marked as `classmethod` and `classinit` at the same time.');
  markers.classmethod = true;
  return func;
}

/**
* Marks a method as class meta-initializer.
* 
* A "class meta-initializer" is a function that is called on the class as soon
* as the class is defined. Any such method that is added to a class definition
* will be called as soon as the class is defined just before it is returned.
* Also, it will NOT be added to the class.
* 
* This function is generally not used alone but rather as a part of mechanisms
* used to provide additional information to a class defintion.
* 
* At the time the given function is called, it is called using the convention:
* 
*   func.call(c, supers, methods, classmethods)
* 
* c:            The class (constructor) is used as the context of the call.
* supers:       An array of all superclasses that were provided for the given
*               class. The first item is the "true" superclass, whereas the
*               remaining items are mixins that are merged with the class
*               prototype.
* methods:      An object mapping names of methods in the class definition
*               to the methods themselves, not including the constructor. Class
*               methods are included in this as well, since they are callable 
*               from instances of the class.
* classmethods: An object mapping names of class methods to the actual
*               class methods.
* classinits:   An object mapping names of class inits to the actual functions
*               (including the current classinit function).
* 
* The classinit function does not modify the function; it merely marks it. Most
* of the work is performed at the time a class definition is processed.
*/
my.classinit = function classinit(func) {
  var markers = func.__markers__ = func.__markers__ || {};
  if (markers.classmethod)
    throw new TypeError(
      'Function "' + my.getFunctionName(func) +
      '" cannot be marked as `classmethod` and `classinit` at the same time.');
  markers.classinit = true;
  return func;
}

var _funcNameRE = /function\s*([\$\w]+)\s*\(/m;

/**
* Returns the name of a given function.
* 
* This will first check for the presence of the `name` attribute on the given
* function object. If defined, its value is returned. If it is not defined,
* the function is converted to a string and parsed to find its name from the
* function definition.
* 
* Returns an empty string "" if the function has no name.
* (Note that the empty string is considered to be a boolean false in JavaScript)
*/
my.getFunctionName = function getFunctionName (func) {
  if (func.name)
    return func.name;
    
  _funcNameRE.lastIndex = 0;
  var matches = _funcNameRE.exec(func.toString());
  if (matches.length < 2)
    return ""
  else
    return matches[1];
}

var _funcArgsRE = /\(([\s\S]*?)\)/;
var _commentsRE = /\/\*[\s\S]*?\*\/|\/\/.*[\n\r]/g;

/**
* Returns the parameter list of the given function as an array.
* 
* The function will be converted to a string and its definition will be parsed
* in order to find the parameter list. 
* 
* If the function accepts no arguments then null is returned.
*/
my.getFunctionParams = function getFunctionParams(func) {
  _funcArgsRE.lastIndex = 0;
  var argList = _funcArgsRE.exec(func.toString())[1];
  _commentsRE.lastIndex = 0;
  argList = argList.replace(_commentsRE,"");
  argList = argList.replace(/\s/g, "");
  if (!argList)
    return null;
  var argNames = argList.split(",");
  return argNames;
}

/**
* Wraps a function with another function to allow it to accept keyword args.
* 
*   myFunc = util.kw(function myFunc (param0[, param1[, ...[, paramN]]]) {
*     // ...code...
*   });
* 
* After applying util.kw(), the function myFunc() above will work using either
* of two calling conventions:
* 
*  myFunc(arg0, arg1, ..., argN);
*  myFunc({param0:arg0, param1:arg1, ..., paramN:argN});
* 
* Notes:
* - Functions passed into this 
* - When using keyword arguments, the function will always receive exactly as
*   many arguments as the function definition says it should take regardless of
*   the number of arguments actually passed. The arguments that were not passed
*   will be set to the `undefined` object and extraneous arguments will be
*   ignored.
* 
* - util.kw() may break a function whose first parameter is meant to accept a
*   plain object. To avoid this, be sure to either pass the plain object as a
*   keyword argument or else pass at least 2 positional arguments. (Passing
*   more than one argument prevents the first argument from being interpreted as
*   a set of keyword arguments.)
* 
* - The function returned will have the same internal name and prototype as the
*   function passed. The function passed can be accessed as the `original`
*   attribute of the function returned.
* 
*/
my.kw = function kw(func) {
  var markers = func.__markers__ || {};
  if (!markers.kw) {
    var funcName = my.getFunctionName(func);
    var funcParams = my.getFunctionParams(func);
    
    if (!funcParams)
      return eval("(function " + funcName + "() { return func.call(this); })");
    
    var newFuncCode = "(function " + funcName + "(kwargs) {\n" +
    "  if (my.isObjectLiteral(kwargs) && arguments.length == 1) {\n" +
    "    return func.call(this, ";
          for (var i in funcParams) {
            newFuncCode += "kwargs." + funcParams[i] +
              (i == funcParams.length - 1 ? ");\n" : ", ");
          }
    newFuncCode +=
    "  }\n" +
    "  else {\n" +
    "    return func.apply(this, arguments); \n" +
    "  }\n" +
    "})";
    var newFunc = eval(newFuncCode);
    newFunc.original = func;
    newFunc.prototype = func.prototype;
    newFunc.__markers__ = my.copyObject(markers, {kw: true});
    return newFunc;
  }
  return func;
}

/**
 * Mixin that enables a state system for the given class.
 * 
 * The states system allows instances of a class to save their current state,
 * or aspects of their current state, so that that state can be loaded again 
 * later. States are saved and loaded according to a set of optional rules
 * that are passed in the second argument. This set of rules will be shared by
 * all instances of the class by default, but can be overridden on a
 * per-instance or even a per-save basis. If no rules are specified, a set of
 * default rules are used.
 * 
 * Make sure that subclasses call the StatesMixin constructor. It is safe to
 * call multiple times as only the first call will have any effect per
 * instance, but it must be called at least once.
 * 
 * About Storage Rules:
 * 
 * A different rule may be specified for each attribute of an instance and
 * specifies how to save and load that attribute. You can also create "virtual
 * attributes" such that an attribute need not actually exist for saving and 
 * loading to occur. A set of rules can be specified in one of three places:
 * 
 * 1.) As the second argument to the `enableStates()` function. In this case,
 *     the rule set can be shared by all instances of a class. The rule 
 *     processor will not have access to instance attributes that are created
 *     during instantiation, so it will only have the methods of the class, its 
 *     superclasses, and the information given in the rule set for determining 
 *     the names and accessor methods of the attributes specified. 
 * 
 * 2.) As an instance-specific rule set. This is done by passing the rule set
 *     to the `setStorageRules()` method of an instance of the class. In this
 *     case, any existing rule set for an instance, including those defined
 *     for the instance's class, are replaced by the new set. Rules for the
 *     class DO NOT cascade into the new rule set defined for the instance.
 * 
 * 3.) At the time a state is saved or loaded.
 * 
 * There are basically six different types of rules, numbered 0 to 5. The type
 * for each rule can be defined explicitly or determined automatically.
 * 
 * A rule set can be specified either as an array or as a plain object that 
 * maps each attribute name to a rule for saving and loading the attribute with 
 * that name.
 * 
 * In the case that a rule set is given as an array, the following procedure is 
 * used to process the rule set:
 * 
 * - For rule types 0-3 below, the rule definition is simply the name of the 
 *   item to be saved or loaded, and the mechanism used to save or load it will 
 *   be based on the presence or absence of the attribute and related
 *   attributes at the time the rule set is processed:
 * 
 * 0. Store Undefined - If none of the searches for rule types 1-3 (below) are 
 *    successful and there does not appear to be any attributes or methods 
 *    associated with the given attribute name, the saver will store an 
 *    "undefined" state for the attribute, meaning that the attribute will be 
 *    deleted if it is present at the time the state is loaded.
 *    
 *    Note that this does not apply when the rule set is specified at the class
 *    level. In this case, the attribute is assumed to exist after instantiation
 *    and the getters and setters behave more like in rule type 1 (below).
 * 
 *      Save Example: state.foo = obj.foo // No attr or related methods found...
 *      Load Example: if (obj.hasOwnProperty("foo") { delete obj.foo; }
 * 
 * 1. Simple Storage - If an attribute is found on the instance as an "own
 *    property" as per the .hasOwnProperty() method, the attribute's value is
 *    stored as-is in the state and will be assigned back to the object again
 *    an a normal attribute when the state is loaded.
 * 
 *      Save Example: state.foo = obj.foo
 *      Load Example: obj.foo = state.foo
 * 
 * 2. Implicit Calculated Storage - If an attribute cannot be found on 
 *    the instance as an "own property" (as per the JavaScript Object method 
 *    .hasOwnProperty), the saver looks for an inherited method with the same 
 *    name as the given attribute name and calls this method without arguments, 
 *    then stores the return value in the state. When the state is loaded, the  
 *    same method will be called again, this time passing the value that the 
 *    method returned when the state was saved. The return value for the 
 *    loading call will be discarded.
 * 
 *      Save Example: state.foo = obj.foo() // "foo" is an inherited method
 *      Load Example: obj.foo(state.foo)
 * 
 * 3. Implicit Accessor Storage - If an inherited method with the 
 *    attribute name cannot be found either, the saver then looks for a getter 
 *    method named `getAttr`, where `attr` is the name of the attribute that 
 *    could not be found.
 * 
 *      Save Example: state.foo = obj.getFoo() // Assume `obj.foo` is undefined
 *      Load Example: obj.setFoo(state.foo)
 * 
 * 4. Explicit Calculated Storage - If a function is passed as a rule instead of
 *    an attr name as a string, this function will be called with the object 
 *    whose state is being saved as the context. The return value will be 
 *    stored as the value for the state. The internal name of the function will 
 *    be used as the storage slot name. If the function is anonymous, an 
 *    arbitrary name will be chosen for the storage slot. When loading the 
 *    state, the same function that was used to save the attribute will be used
 *    to load it. The value that was returned earlier will be passed to the
 *    function as a single argument, again with the object whose's state is
 *    being saved as the context.
 * 
 *      Save Example: state.foo = someFunc.call(obj)
 *      Load Example: someFunc.call(obj, state.foo)
 * 
 * 5. Explicit Accessor Storage - If an array of two functions is passed as a
 *    rule, the functions are interpreted as a [getter,setter] pair for an
 *    attribute that is theoretically associated with those functions. When the 
 *    attribute is saved, the getter's return value is stored. When the 
 *    attribute is loaded, the stored value is passed to the setter. In both 
 *    cases the object whose state is being saved will be the context object. 
 *    Assuming the internal name of the functions match the usual "getAttr" and 
 *    "setAttr" nomenclature, the name of the value for the storage slot will 
 *    be determined from the functions. Otherwise, an arbittary name will be 
 *    determined for the storage slot.
 * 
 *      Save Example: state.foo = someGetterFunc.call(obj)
 *      Load Example: someSetterFunc.call(obj, state.foo)
 * 
 * In the case that the rules are specified as a plain object, the keys
 * indicate the attribute names and the values indicate how to save and load it.
 * The following additional processing applies:
 * 
 * - Rule types 0-3 can be explicitly specified by passing the number of that
 *   rule. 
 * - When explicitly specifying rule type 0, the value of the `keepIfUndefined` 
 *   argument for the `processStorageRules()` method is ignored. This means the
 *   setter will always delete the attribute associated with the rule if the
 *   attribute exists.
 * - For rule types 4 and 5, specify the function or array, respectively, 
 *   rather than the rule number. The key for the rule will be used for the 
 *   name of the storage slot rather than the name of the function(s).
 * 
 * Class-Level Storage Rules:
 * 
 * A set of storage rules can be specified at the class level using the
 * function `util.SetStorageRules`. To do this, call the function somewhere
 * within the method list of any class that inherits from StatesMixin, passing
 * the desired storage rule set as the argument. A classinit function will be
 * generated that will give the class the storage rules provided. Example:
 * 
 *    MyStatesEnabledClass = util.extend(
 *      [MyBase, util.StatesMixin],
 * 
 *      function MyStatesEnabledClass(v) {
 *        MyBase.call(this);
 *        util.StatesMixin.call(this);
 *        this._value = v;
 *      },
 * 
 *      function getValue() {
 *        return this._value;
 *      },
 * 
 *      function setValue(v) {
 *        this._value = v;
 *      },
 * 
 *      util.SetStorageRules([
 *        "value"
 *      ]);
 *   )
 * 
 * Other caveats when using StatesMixin:
 * 
 * - If no rule set is specified for a class, for the instance being saved, or
 *   passed to the saving or loading method, then a set of default rules will be 
 *   generated at the time a state is saved or loaded. Only the instance's own
 *   attributes are considered by this rule set. No getter, setter, or accessor 
 *   methods will be considered (as there is no safe way to determine what they 
 *   are), and no inherited attribute values will be considered.
 * 
 * - All rule sets passed into the state system are converted to plain objects
 *   and use rule type 5 and are stored using this format. Keep this in mind
 *   when reading the rule set for any state, instance, or class, as that is the
 *   format of the rule set object that will be returned.
 * 
 * - Rule sets created by the state system have an attribute called 
 *   "__processed__" which is used internally for optimization purposes. It is 
 *   important to note that only the presence of this attribute is important 
 *   and the actual value is assumed to be unused and irrelevant. Therefore, 
 *   you must understand that if the attribute is present for any rules object 
 *   that is passed to a method of the state system, THIS ATTRIBUTE MAY BE 
 *   MODIFIED.
 * 
 * - The state system does not store any attribute that is used by the state
 *   system itself unless rules are explicitly defined to do so. This
 *   includes the following: __states__, __stateRules__, __storageRules__.
 */
my.StatesMixin = my.extend (
  Object,

  function StatesMixin () {
    if (!this.__states__) {
      this.__states__ = {};
      this.__stateRules__ = {};
    }
  },

  function _createRule (rules, type, aName, ruleValue, keepIfUndefined) {
    switch (type) {
      case 0:
        ruleValue = [
          function(){ return this[aName]},
          keepIfUndefined ? 
            function (v) { this[aName] = v; } :
            function() { delete this[aName]; }
        ];
        break;
      case 1:
        ruleValue = [
          function () { return this[aName]; },
          function (v) { this[aName] = v; }
        ];
        break;
      case 2:
        ruleValue = [this[aName], this[aName]];
        break;
      case 3:
        var getterName = "get" + aName.slice(0,1).toUpperCase() +aName.slice(1);
        var setterName = "set" + aName.slice(0,1).toUpperCase() +aName.slice(1);
        ruleValue = [this[getterName], this[setterName]];
        break;
      case 4:
        aName = aName || my.getFunctionName(ruleValue);
        if (!aName)
          aName = my.idnString();
        ruleValue = [ruleValue, ruleValue];
        break;
      case 5:
        if (!(ruleValue[0] instanceof Function
         && ruleValue[1] instanceof Function ))
          throw new TypeError("Invalid array for rule '" + 
            aName + "': array members must be functions.");
        aName = aName || my.getFunctionName(ruleValue[0]);
        if (!aName)
          aName = my.idnString();
        break;
      default:
        throw TypeError("Unknown rule type: " + ruleType);
    }
    rules[aName] = ruleValue;
  },

  /**
  * Process a set of storage rules.
  * 
  *   obj.processStorageRules([rules[, state[, keepIfUndefined]]) --> rules
  * 
  * Process and verify the given rules or rule and state combination.
  * This will always return a plain object where each value is a
  * [getter, setter] array pair (rule type 5). If keepIfUndefined is true, the
  * setters will not delete attributes that were not present at the time of
  * rule checking, otherwise they will.
  */
  function processStorageRules(rules, state, keepIfUndefined) {
    var aName, i, rule, ruleValue, newRules, getterName, setterName, ownRules,
        isInternal, internals;
    // No rules were passed; try to find or create some.
    if (!rules) {
      // Rules exist for the instance or class; use these.
      if (this.__storageRules__) {
        rules = this.__storageRules__;
        if (!(rules && rules.hasOwnProperty("__processed__"))) {
          // Recursion alert! This should never recurse more than 1 level deep.
          rules = this.processStorageRules(rules, state, keepIfUndefined);
        }
      }
      // Rules do NOT exist for the instance or class; create a default set.
      else {
        rules = {};
        // Create default rule set based on a state, if one was given.
        if (state) {
          for (aName in state)
            this._createRule(rules, 1, aName);
          for (aName in this) {
            if (!(aName in state))
              this._createRule(rules, 0, aName, undefined, keepIfUndefined);
          }
        }
        // Create default rule set based on instance's actual state
        else {
          for (aName in this) {
            // Only use owned, non-internal properties
            if (this.hasOwnProperty(aName) &&
             _stateInternals.indexOf(aName) == -1) {
              this._createRule(rules, 1, aName);
            }
          }
        }
      }
    }
    // Rules were passed, but have not been processed
    if (!rules.hasOwnProperty("__processed__")) {
      newRules = {};
      if (rules instanceof Array) {
        for (i in rules) {
          rule = rules[i];
          if (rule instanceof Function)
            this._createRule(newRules, 4, undefined, rule)
          else if (rule instanceof Array)
            this._createRule(newRules, 5, undefined, rule)
          else if (typeof(rule) == "string" || rule instanceof String) {
            getterName = "get" + rule.slice(0,1).toUpperCase() + rule.slice(1);
            if (this.hasOwnProperty(rule))
              this._createRule(newRules, 1, rule)
            else if (this[rule] instanceof Function)
              this._createRule(newRules, 2, rule)
            else if (this[getterName] instanceof Function)
              this._createRule(newRules, 3, rule)
            else
              this._createRule(newRules, 0, rule, undefined, keepIfUndefined);
          }
          else
            throw TypeError("Unknown rule type: " + rule);
        }
        rules = newRules;
      }
      // Rules is not an array
      else {
        // Normalize the format of the rules
        for (aName in rules) {
          ruleValue = rules[aName];
          getterName = "get" + aName.slice(0,1).toUpperCase() +aName.slice(1);
          if (ruleValue instanceof Function)
            ruleType = 4
          else if (ruleValue instanceof Array)
            ruleType = 5
          else if (
           !(typeof(ruleValue) == "number" || ruleValue instanceof Number))
            throw new TypeError("Unknown rule type: " + ruleValue);
          // keepIfUndefined is deliberately false here so that class-level 
          // rules can be explicitly defined to delete attributes that should 
          // not exist when the state is loaded.                 vvvvv
          this._createRule(newRules, ruleType, aName, ruleValue, false);
        }
        rules = newRules;
      }
      rules.__processed__ = 1;
    }
    
    // State validation
    if (state) {
      // Temporarily remove old rules so state can be verified without them
      ownRules = this.hasOwnProperty("__storageRules__") ?
        this.__storageRules__ : null;
      delete this.__storageRules__;
      // Verify that the given state is valid for the current rule set
      for (aName in state) {
        if (!(aName in rules)) {
          throw new my.ValueError(
          "No rule for attribute \"" + aName + "\".");
        }
      }
      // Restore rules if necessary
      if (ownRules)
        this.__storageRules__ = ownRules;
    }
    
    return rules;
  },

  /**
  * Get current state of the object.
  * 
  *   obj.getState() --> state
  *
  * Return the current state of the object according to the storage rules
  * for the instance or class.
  * 
  *   obj.getState(rules[, keepIfUndefined]) --> state
  * 
  * Return the current state of the object according to the given rules.
  * Note that this same set of rules will have to be passed to setState().
  */
  function getState(rules) {
    rules = this.processStorageRules(rules);
    delete rules.__processed__ ;
    var state = {};
    for (var aName in rules) {
      state[aName] = rules[aName][0].call(this);
    }
    rules.__processed__ = 1;
    return state;
  },
  
  /**
  * Set current state of the object.
  * 
  *   obj.setState(state) --> state
  * 
  * Set the state of the object according to the state data passed and the
  * instance or class storage rules.
  * 
  *   obj.setState(state, rules[, keepIfUndefined]) --> state
  * 
  * Set the state of the object according to the state data and storage
  * rules passed.
  */
  function setState(state, rules) {
    rules = this.processStorageRules(rules, state);
    for (var aName in state) {
      rules[aName][1].call(this, state[aName]);
    }
    return state;
  },

  /**
  * Save current state to given state name.
  * 
  *   obj.saveState(name) --> state
  * 
  * Saves the instance's current state to the state with the given name
  * according to the class or instance storage rules. If the state already 
  * existed, it is overridden.
  * 
  *   obj.saveState(name, rules) --> state
  * 
  *  Saves the instance's current state to the state with the given name
  *  according to the rules given. If the state already existed, it is
  *  overridden.
  */
  function saveState(name, rules, keepIfUndefined) {
    var states = this.__states__,
        stateRules = this.__stateRules__,
        state = this.getState(rules, keepIfUndefined);
    states[name] = state;
    stateRules[name] = rules;
    return state;
  },
 
  /**
  * Loads the state from the given state name.
  * 
  *   .loadState(name) --> state
  * 
  * Loads the state with the given name according to the storage rules used
  * to save the state.
  */
  function loadState(name) {
    var states = this.__states__,
        stateRules = this.__stateRules__,
        state = states[name],
        rules = stateRules[name];
    if (!state)
      throw new Error("No state named \"" + name  + "\"");
    this.setState(state, rules);
    return state;
  },
  
  /**
  * Delete the state with the given name.
  * 
  *   obj.deleteState(name)
  */
  function deleteState(name) {
    var states = this.__states__,
        stateRules = this.__stateRules__,
        state = states[name];
    if (state) {
      delete states[name];
      delete this.__stateRules__[name];
    }
  },
  
  /**
  * Import a state into the given state name.
  * 
  *   obj.importState(name, state) --> state
  * 
  * Import the given state into the given state slot to load with the class 
  * or instance rules. This does not actually apply the state but stores it 
  * for use later.
  * 
  *   obj.importState(name, state, rules[, keepIfUndefined]) --> state
  * 
  * Import the given state into the given state slot to load with the given 
  * rules. This does not actually apply the state but stores it for use later.
  */
  function importState(name, state, rules, keepIfUndefined) {
    state = my.copyObject(state);
    this.__states__[name] = state;
    this.__stateRules__[name] =
      this.processStorageRules(rules, keepIfUndefined);
    return state;
  },
  
  /**
  * Export a saved state.
  * 
  *   obj.exportState(name) --> state
  * 
  * Returns the state with the given name as a plain object.
  */
  function exportState(name) {
    var state = this.__states__[name];
    if (state)
      return my.copyObject(state)
    else
      return null;
  },
  
  /**
  * Save a modified copy of an existing saved state.
  * 
  *  obj.deriveState(name1, name2[, changes]) --> state
  * 
  * Duplicate the save state at name1, modify it according to the given
  * changes (if any), and save the modified copy into name2.
  */
  function deriveState(name1, name2, changes) {
    var state1 = this.exportState(name1),
        changed = my.copyObject(state1, changes),
        state2 = this.importState(name2, changed,
          this.exportStorageRules(name1));
    return state2;
  },
  
  /**
  * Export the names of all saved states.
  * 
  *   .exportStateNames() --> names
  *  
  * Returns an array of the names of all states that have been saved.
  */
  function exportStateNames() {
    var names = [];
    for (name in this.__states__)
      names.push(name);
    return names;
  },
  
  /**
  * Export storage rules of a saved state.
  * 
  *   obj.exportStorageRules(name) --> rules
  * 
  * Returns the rules associated with the given state as a plain object.
  */
  function exportStorageRules(name) {
    var rules = this.__stateRules__[name];
    if (rules)
      return my.copyObject(rules)
    else
      return null;
  },
  
  /**
  * Get the instance-level storage rules.
  * 
  *   obj.getOwnStorageRules() --> rules
  * 
  * Returns the per-instance storage rules for the instance. If there are no
  * per-instance rules, null is returned.
  */
  function getOwnStorageRules() {
    var rules;
    if (this.hasOwnProperty("__storageRules__"))
      return my.copyObject(this.__storageRules__)
    else
      return null;
  },
  
  /**
  * Set the instance-level storage rules for the object.
  *
  *   obj.setOwnStorageRules(rules[, keepIfUndefined])
  * 
  * Set the per-instance storage rules for the instance. The previous set of
  * rules are overridden.
  */
  function setOwnStorageRules(rules, keepIfUndefined) {
    this.__storageRules__ =
      this.processStorageRules(rules, undefined, keepIfUndefined)
  }
);

var _stateInternals = ["__states__", "__stateRules__", "__storageRules__"];

/**
* Used in conjunction with StatesMixin to define class-level storage rules.
* 
* Use this function within the definition of a class that inherits from the
* StatesMixin class to define class-level storage rules for that class.
* 
* The argument should be a rules object of the same form that is passed to the
* `rules` parameter of the methods of the StatesMixin class.
* 
* Returns a classinit function that will be called when the new class is
* about to be finalized.
*/
my.SetStorageRules = function SetStorageRules(rules) {
  var SetStorageRules_worker = my.classinit(
    function SetStorageRules_worker () {
      if (rules) {
        var fakeInstance = my.clone(this.prototype);
        rules = fakeInstance.processStorageRules(rules, undefined, true);
      }
      this.prototype.__storageRules__ = rules;
    }
  );
  return SetStorageRules_worker;
}

var _idn = 0;
/**
 * Returns an arbitrary numberic identification string beginning with "_".
 * 
 * Used to generate a unique variable name for every call.
 */
my.idnString = function idnString() {
  return "_" + (_idn++) ;
}

/**
 * Thrown when an incorrect value of the correct type is passed to a function.
 */
my.ValueError = my.extend(
  Error,
  
  function ValueError(message) {
    Error.apply(this, arguments);
    this.message = message;
  },
  
  {
    name: "util.ValueError"
  }
);

/**
 * Returns whether or not the given value responds to a regular number.
 * This only returns true if the value is not NaN and finite.
 */
my.isNumber = function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

// End of module `util`
return my; })(); }